package com.lucien.framework.web.login;

import com.alibaba.fastjson.JSON;
import com.lucien.common.utils.redis.RedisCache;
import com.lucien.framework.exception.GlobalException;
import com.lucien.framework.shiro.utils.JWTUtils;
import com.lucien.common.fornt.UserFront;
import com.lucien.system.domain.SysUser;
import com.lucien.system.mapper.SysUserMapper;
import com.lucien.system.service.SysUserService;
import io.lettuce.core.RedisException;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

/**
 * @Author: Lucien
 * @Description: 登录接口
 * @Date: Created in 2021/5/2
 */
@Component
public class SysLoginService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserService userService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    public UserFront login(String username, String password) {
        SysUser sysUser = userService.selectByUsername(username);
        String role = userService.getUserRoles(sysUser.getId());
        UserFront userFront = new UserFront();
        Subject subject = SecurityUtils.getSubject();
        //登录成功标识
        boolean loginSuccess = false;

        UsernamePasswordToken token = new UsernamePasswordToken(username, DigestUtils.md5DigestAsHex(password.getBytes()));

        try {
            subject.login(token);
            userFront.setUserId(sysUser.getId());
            userFront.setUsername(username);
            userFront.setUserProfile(sysUser.getUserProfile());
            userFront.setRoles(role);
            userFront.setMessage("登录成功");
            userFront.setEmail(sysUser.getEmail());
            userFront.setGender(sysUser.getGender());
            loginSuccess = true;
        }
        catch (UnknownAccountException | IncorrectCredentialsException uae) { // 账号不存在 // 账号与密码不匹配
            userFront.setMessage("用户名与密码不匹配，请检查后重新输入！");
        }
        catch (LockedAccountException lae) { // 账号已被锁定
            userFront.setMessage("该账户已被锁定，如需解锁请联系管理员！");
        }
        catch (AuthenticationException ae) { // 其他身份验证异常
            userFront.setMessage("登录异常，请联系管理员！");
        }
        catch (Exception e) {
            userFront.setMessage("登录失败");
        }

        if (loginSuccess) {
            sysUser.setUserStateId(1);
            if (userMapper.updateByPrimaryKey(sysUser) != 1) {
                throw new GlobalException("{\"code\":500,\"msg\":\"修改用户状态错误\"}");
            }
            userFront.setUserState(sysUser.getUserStateId());
            //登录成功 生成token
            String jwtToken = JWTUtils.sign(username, JWTUtils.SECRET);

            userFront.setToken(jwtToken);
            try {
                redisCache.setCacheObject("TOKEN:" + jwtToken, JSON.toJSON(userFront));
                redisCache.expire("TOKEN:" + jwtToken, JWTUtils.EXPIRE_TIME);
            } catch (RedisException e) {
                e.printStackTrace();
            }
        }
        return userFront;
    }

    /**
     * 退出登陆
     * @param token
     * @return
     */
    public String logout(String token) {
        try {
            if (redisCache.getCacheObject("TOKEN:" + token) == null) {
                return "退出成功";
            }
            UserFront loginUser = JSON.toJavaObject(redisCache.getCacheObject("TOKEN:" + token), UserFront.class);
            userService.updateUserStatus(loginUser.getUsername(), 2);
            redisCache.deleteObject("TOKEN:" + token);
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "退出成功";
    }

    public UserFront getLoginUser(String token) {
        UserFront userFront = JSON.toJavaObject(redisCache.getCacheObject("TOKEN:" + token), UserFront.class);
        return userFront;
    }
}
